import java.util.ArrayList;
import java.util.Date;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Scanner;

public class CinemaSystem {
    private List<User> users = new ArrayList<>();
    private List<Movie> movies = new ArrayList<>();
    private List<Hall> halls = new ArrayList<>();
    private List<Show> shows = new ArrayList<>();
    private User currentUser;
    private SalesReport salesReport = new SalesReport();

    public CinemaSystem() {
        initData();
    }

    private void initData() {
        // 初始化默认管理员
        users.add(new Admin("admin001", "admin", "ynuinfo#777", "13800138000"));
        // 初始化放映厅
        halls.add(new Hall("h1", "黄金厅", 8, 10));
        halls.add(new Hall("h2", "白银厅", 10, 12));
        halls.add(new Hall("h3", "翡翠厅",7 ,8 ));
        halls.add(new Hall("h4", "钻石厅",7 ,8 ));
        halls.add(new Hall("h5", "宝石厅",8 ,9 ));


        // 添加示例影片
        movies.add(new Movie("m1", "复仇者联盟4", "安东尼·罗素", "小罗伯特·唐尼,克里斯·埃文斯", "漫威超级英雄电影", 181, 8.5));
        movies.add(new Movie("m2", "流浪地球2", "郭帆", "吴京,李雪健", "科幻灾难电影", 173, 8.3));
    }

    public void start() {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            if (currentUser == null) {
                showLoginMenu(scanner);
            } else {
                if (currentUser instanceof Admin) {
                    showAdminMenu(scanner);
                } else if (currentUser instanceof Manager) {
                    showManagerMenu(scanner);
                } else if (currentUser instanceof FrontDesk) {
                    showFrontMenu(scanner);
                }
            }
        }
    }

    private void showLoginMenu(Scanner scanner) {
        System.out.println("\n=== 影院管理系统 ===");
        System.out.println("1. 登录");
        System.out.println("2. 退出");
        System.out.print("请选择: ");
        int choice = getValidInt(scanner, 1, 2);
        if (choice == 1) {
            login(scanner);
        } else {
            System.out.println("感谢使用影院管理系统，再见！");
            System.exit(0);
        }
    }

    private void login(Scanner scanner) {
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();
        for (User user : users) {
            if (user.getUsername().equals(username) && user.login(password)) {
                currentUser = user;
                System.out.println("登录成功，欢迎" + user.getUserType() + "[" + username + "]");
                return;
            }
        }
        System.out.println("用户名或密码错误");
    }

    private void showAdminMenu(Scanner scanner) {
        while (true) {
            System.out.println("\n=== 管理员菜单 ===");
            System.out.println("1. 添加用户");
            System.out.println("2. 删除用户");
            System.out.println("3. 重置用户密码");
            System.out.println("4. 查看所有用户");
            System.out.println("5. 查看销售报表");
            System.out.println("6. 退出登录");
            System.out.print("请选择: ");
            int choice = getValidInt(scanner, 1, 6);

            switch (choice) {
                case 1:
                    addUser(scanner);
                    break;
                case 2:
                    deleteUser(scanner);
                    break;
                case 3:
                    resetPassword(scanner);
                    break;
                case 4:
                    viewAllUsers();
                    break;
                case 5:
                    viewSalesReport(scanner);
                    break;
                case 6:
                    currentUser = null;
                    System.out.println("已退出登录");
                    return;
            }
        }
    }

    private void addUser(Scanner scanner) {
        System.out.println("\n=== 添加用户 ===");
        System.out.println("1. 添加管理员");
        System.out.println("2. 添加经理");
        System.out.println("3. 添加前台");
        System.out.print("请选择用户类型: ");
        int type = getValidInt(scanner, 1, 3);

        System.out.print("用户ID: ");
        String id = scanner.nextLine();
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();
        System.out.print("手机号: ");
        String phone = scanner.nextLine();

        User newUser = null;
        String userType = "";

        switch (type) {
            case 1:
                newUser = new Admin(id, username, password, phone);
                userType = "管理员";
                break;
            case 2:
                newUser = new Manager(id, username, password, phone);
                userType = "经理";
                break;
            case 3:
                newUser = new FrontDesk(id, username, password, phone);
                userType = "前台";
                break;
        }

        try {
            ((Admin) currentUser).addUser(newUser, users);
            System.out.println("成功添加" + userType + "[" + username + "]");
        } catch (IllegalArgumentException e) {
            System.out.println("添加失败: " + e.getMessage());
        }
    }

    private void deleteUser(Scanner scanner) {
        System.out.print("\n请输入要删除的用户ID: ");
        String userId = scanner.nextLine();

        try {
            ((Admin) currentUser).deleteUser(userId, users);
            System.out.println("成功删除用户");
        } catch (IllegalArgumentException e) {
            System.out.println("删除失败: " + e.getMessage());
        }
    }

    private void resetPassword(Scanner scanner) {
        System.out.print("\n请输入要重置密码的用户ID: ");
        String userId = scanner.nextLine();

        User targetUser = null;
        for (User user : users) {
            if (user.getId().equals(userId)) {
                targetUser = user;
                break;
            }
        }

        if (targetUser == null) {
            System.out.println("用户不存在");
            return;
        }

        ((Admin) currentUser).resetPassword(targetUser);
        System.out.println("已重置用户[" + targetUser.getUsername() + "]的密码为: 123456");
    }

    private void viewAllUsers() {
        System.out.println("\n=== 所有用户 ===");
        for (User user : users) {
            System.out.printf("ID: %-10s 用户名: %-10s 类型: %-10s 注册时间: %s%n",
                    user.getId(), user.getUsername(), user.getUserType(), user.getRegisterTime());
        }
    }

    private void viewSalesReport(Scanner scanner) {
        System.out.println("\n=== 销售报表 ===");
        System.out.println("1. 今日报表");
        System.out.println("2. 本周报表");
        System.out.println("3. 本月报表");
        System.out.print("请选择: ");
        int choice = getValidInt(scanner, 1, 3);

        switch (choice) {
            case 1:
                salesReport.dailyReport(shows);
                break;
            case 2:
                salesReport.weeklyReport(shows);
                break;
            case 3:
                salesReport.monthlyReport(shows);
                break;
        }
    }

    private void showManagerMenu(Scanner scanner) {
        while (true) {
            System.out.println("\n=== 经理菜单 ===");
            System.out.println("1. 添加影片");
            System.out.println("2. 查看所有影片");
            System.out.println("3. 添加场次");
            System.out.println("4. 修改场次");
            System.out.println("5. 查看所有场次");
            System.out.println("6. 查看销售报表");
            System.out.println("7. 退出登录");
            System.out.print("请选择: ");
            int choice = getValidInt(scanner, 1, 7);

            switch (choice) {
                case 1:
                    addMovie(scanner);
                    break;
                case 2:
                    viewAllMovies();
                    break;
                case 3:
                    addShow(scanner);
                    break;
                case 4:
                    updateShow(scanner);
                    break;
                case 5:
                    viewAllShows();
                    break;
                case 6:
                    viewSalesReport(scanner);
                    break;
                case 7:
                    currentUser = null;
                    System.out.println("已退出登录");
                    return;
            }
        }
    }

    private void addMovie(Scanner scanner) {
        System.out.println("\n=== 添加影片 ===");
        System.out.print("影片ID: ");
        String id = scanner.nextLine();
        System.out.print("影片名称: ");
        String name = scanner.nextLine();
        System.out.print("导演: ");
        String director = scanner.nextLine();
        System.out.print("演员: ");
        String actors = scanner.nextLine();
        System.out.print("简介: ");
        String introduction = scanner.nextLine();
        System.out.print("时长(分钟): ");
        int duration = getValidInt(scanner, 1, 300);
        System.out.print("评分(0-10): ");
        double rating = getValidDouble(scanner, 0, 10);

        Movie movie = new Movie(id, name, director, actors, introduction, duration, rating);
        ((Manager) currentUser).addMovie(movie, movies);
        System.out.println("成功添加影片[" + name + "]");
    }

    private void viewAllMovies() {
        System.out.println("\n=== 所有影片 ===");
        for (Movie movie : movies) {
            System.out.printf("ID: %-5s 名称: %-20s 导演: %-15s 评分: %.1f 时长: %d分钟%n",
                    movie.getId(), movie.getName(), movie.getDirector(),
                    movie.getRating(), movie.getDuration());
        }
    }

    private void addShow(Scanner scanner) {
        System.out.println("\n=== 添加场次 ===");

        System.out.println("可用影片:");
        for (int i = 0; i < movies.size(); i++) {
            System.out.printf("%d. %s%n", i + 1, movies.get(i).getName());
        }
        System.out.print("请选择影片序号: ");
        int movieIndex = getValidInt(scanner, 1, movies.size()) - 1;
        Movie movie = movies.get(movieIndex);

        System.out.println("可用放映厅:");
        for (int i = 0; i < halls.size(); i++) {
            System.out.printf("%d. %s (%d排%d座)%n",
                    i + 1, halls.get(i).getName(),
                    halls.get(i).getRows(), halls.get(i).getCols());
        }
        System.out.print("请选择放映厅序号: ");
        int hallIndex = getValidInt(scanner, 1, halls.size()) - 1;
        Hall hall = halls.get(hallIndex);

        System.out.print("放映时间(格式: yyyy-MM-dd HH:mm): ");
        String timeStr = scanner.nextLine();
        Date showTime = DateUtil.parse(timeStr);

        System.out.print("票价: ");
        double price = getValidDouble(scanner, 1, 1000);

        String showId = "s" + (shows.size() + 1);
        Show show = new Show(showId, movie, hall, showTime, price);

        try {
            ((Manager) currentUser).addShow(show, shows);
            System.out.println("成功添加场次[" + movie.getName() + " - " + DateUtil.format(showTime) + "]");
        } catch (IllegalArgumentException e) {
            System.out.println("添加失败: " + e.getMessage());
        }
    }

    private void updateShow(Scanner scanner) {
        System.out.println("\n=== 修改场次 ===");

        System.out.println("现有场次:");
        for (int i = 0; i < shows.size(); i++) {
            Show show = shows.get(i);
            System.out.printf("%d. %s - %s - %s - 票价: %.2f%n",
                    i + 1, show.getMovie().getName(),
                    show.getHall().getName(),
                    DateUtil.format(show.getShowTime()),
                    show.getPrice());
        }

        System.out.print("请选择要修改的场次序号: ");
        int showIndex = getValidInt(scanner, 1, shows.size()) - 1;
        Show oldShow = shows.get(showIndex);

        System.out.println("当前信息:");
        System.out.printf("影片: %s%n", oldShow.getMovie().getName());
        System.out.printf("放映厅: %s%n", oldShow.getHall().getName());
        System.out.printf("时间: %s%n", DateUtil.format(oldShow.getShowTime()));
        System.out.printf("票价: %.2f%n", oldShow.getPrice());

        System.out.println("\n新信息:");
        System.out.print("放映时间(留空不修改): ");
        String timeStr = scanner.nextLine();
        Date newTime = timeStr.isEmpty() ? oldShow.getShowTime() : DateUtil.parse(timeStr);

        System.out.print("票价(留空不修改): ");
        String priceStr = scanner.nextLine();
        double newPrice = priceStr.isEmpty() ? oldShow.getPrice() : Double.parseDouble(priceStr);

        Show newShow = new Show(oldShow.getShowId(), oldShow.getMovie(),
                oldShow.getHall(), newTime, newPrice);

        try {
            ((Manager) currentUser).updateShow(newShow, shows);
            System.out.println("成功修改场次");
        } catch (IllegalArgumentException e) {
            System.out.println("修改失败: " + e.getMessage());
        }
    }

    private void viewAllShows() {
        System.out.println("\n=== 所有场次 ===");
        for (Show show : shows) {
            System.out.printf("ID: %-5s 影片: %-20s 放映厅: %-10s 时间: %s 票价: %.2f 剩余座位: %d/%d%n",
                    show.getShowId(), show.getMovie().getName(),
                    show.getHall().getName(), DateUtil.format(show.getShowTime()),
                    show.getPrice(), show.getHall().getAvailableSeats(),
                    show.getHall().getRows() * show.getHall().getCols());
        }
    }

    private void showFrontMenu(Scanner scanner) {
        while (true) {
            System.out.println("\n=== 前台菜单 ===");
            System.out.println("1. 售票");
            System.out.println("2. 退票");
            System.out.println("3. 查看所有场次");
            System.out.println("4. 退出登录");
            System.out.print("请选择: ");
            int choice = getValidInt(scanner, 1, 4);

            switch (choice) {
                case 1:
                    sellTicket(scanner);
                    break;
                case 2:
                    refundTicket(scanner);
                    break;
                case 3:
                    viewAllShows();
                    break;
                case 4:
                    currentUser = null;
                    System.out.println("已退出登录");
                    return;
            }
        }
    }

    private void sellTicket(Scanner scanner) {
        System.out.println("\n=== 售票 ===");

        System.out.println("现有场次:");
        for (int i = 0; i < shows.size(); i++) {
            Show show = shows.get(i);
            System.out.printf("%d. %s - %s - %s - 票价: %.2f 剩余座位: %d/%d%n",
                    i + 1, show.getMovie().getName(),
                    show.getHall().getName(),
                    DateUtil.format(show.getShowTime()),
                    show.getPrice(),
                    show.getHall().getAvailableSeats(),
                    show.getHall().getRows() * show.getHall().getCols());
        }

        System.out.print("请选择场次序号: ");
        int showIndex = getValidInt(scanner, 1, shows.size()) - 1;
        Show show = shows.get(showIndex);

        System.out.print("请输入顾客手机号: ");
        String phone = scanner.nextLine();

        System.out.print("请输入要购买的座位数: ");
        int seatCount = getValidInt(scanner, 1, show.getHall().getAvailableSeats());

        List<String> seatIds = new ArrayList<>();
        for (int i = 0; i < seatCount; i++) {
            System.out.printf("请输入第%d个座位号(格式: 行-列): ", i + 1);
            String seatId = scanner.nextLine();
            seatIds.add(seatId);
        }

        try {
            Ticket ticket = ((FrontDesk) currentUser).sellTicket(show, seatIds, phone);
            System.out.println("\n=== 售票成功 ===");
            System.out.printf("票号: %s%n", ticket.getId());
            System.out.printf("影片: %s%n", show.getMovie().getName());
            System.out.printf("放映厅: %s%n", show.getHall().getName());
            System.out.printf("时间: %s%n", DateUtil.format(show.getShowTime()));
            System.out.printf("座位: %s%n", String.join(", ", seatIds));
            System.out.printf("总价: %.2f%n", ticket.getPrice() * seatCount);
        } catch (IllegalArgumentException e) {
            System.out.println("售票失败: " + e.getMessage());
        }
    }

    private void refundTicket(Scanner scanner) {
        System.out.print("\n请输入要退票的票号: ");
        String ticketId = scanner.nextLine();

        try {
            ((FrontDesk) currentUser).refundTicket(ticketId, shows);
            System.out.println("退票成功");
        } catch (IllegalArgumentException e) {
            System.out.println("退票失败: " + e.getMessage());
        }
    }

    private int getValidInt(Scanner scanner, int min, int max) {
        while (true) {
            try {
                int num = Integer.parseInt(scanner.nextLine());
                if (num >= min && num <= max) return num;
                System.out.printf("请输入%d-%d之间的数字: ", min, max);
            } catch (NumberFormatException e) {
                System.out.print("输入无效，请重新输入: ");
            }
        }
    }

    private double getValidDouble(Scanner scanner, double min, double max) {
        while (true) {
            try {
                double num = Double.parseDouble(scanner.nextLine());
                if (num >= min && num <= max) return num;
                System.out.printf("请输入%.1f-%.1f之间的数字: ", min, max);
            } catch (NumberFormatException e) {
                System.out.print("输入无效，请重新输入: ");
            }
        }
    }
}